package advice;
// 以下是JavaDoc注释，用于描述类的作者、日期等信息
/**
 * @author 路老师 // 作者信息
 * @date 2025/6/5 // 创建日期
 * 无精神，不编程！无乐趣，不编程！ // 编程格言
 * “调试：与bug共舞的艺术。” // 调试格言
 */

// 导入Spring框架相关类和自定义类
import advice.MyAfterAdvice;
import advice.MyAroundAdvice;
import advice.MyBeforeAdvice;
import dao.UserDaoImpl;
import entity.Address;
import entity.Student;
import entity.User;
import factory.factoryBean;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.*;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import service.UserServiceImpl;

import javax.sql.DataSource;
import java.io.IOException;
import java.util.*;
//声明这是一个Spring配置类（）核心注解
@Configuration
//启用AspectJ自动代理（支持Aop切面编程）
@EnableAspectJAutoProxy
//启用声明式事务管理
@EnableTransactionManagement
//加载类路径下的jdbc。properties属性文件
@PropertySource("classpath:jdbc.properties")
//自动扫描指定包中的组件（service，factory，dao包）
@ComponentScan(basePackages = {"service","factory","dao"})

public class AppConfig {
    //---------------------1,基础Bean配置--------------------
    //创建UserDaoImpl的Bean实例
    //@return UserDaoImpl实例（数据访问对象）
    @Bean
    public UserDaoImpl userDAO() {
        return new UserDaoImpl(); // 直接实例化DAO对象
    }


    /**
     * 创建UserService实现类的Bean
     * 演示手动依赖注入（将userDAO注入到service中）
     * @return 配置好的UserService实例
     */
    @Bean
    public UserServiceImpl userService() {
        UserServiceImpl service = new UserServiceImpl();
        // 手动注入依赖（调用userDAO()方法获取Bean）
        service.setUserDAO(userDAO());
        return service;
    }

    /**
     * 创建Address实体类的Bean
     * @return 配置好的Address实例
     */
    @Bean
    public Address addr() {
        Address addr = new Address();
        addr.setId(1);       // 设置ID属性
        addr.setCity("bj");   // 设置城市属性
        return addr;
    }

    /**
     * 通过FactoryBean创建复杂对象
     * 实际返回的是FactoryBean.getObject()的结果
     * @return 自定义的工厂Bean
     */
    @Bean
    public FactoryBean conn() {
        return new factoryBean(); // 返回自定义工厂Bean实例
    }

    // ============== 2. 复杂对象配置 ==============
//    /**
//     * 创建User实体类的Bean（原型作用域）
//     * 每次获取都会创建新实例
//     * @return 配置完整的User实例
//     */
//    @Bean
//    @Scope("prototype")  // 设置为原型作用域（非单例）
//    public User user() {
//        User user = new User();
//        user.setId(10);
//        user.setPassword("1234578");
//        user.setUsername("xiaozuf");
//        user.setBirthday("20222/3/5");
//
////        // 设置数组类型属性
////        user.setHobbys(new String[]{"football", "basketball"});
////
////        // 设置List集合属性
////        user.setNames(Arrays.asList("aaa", "bbb"));
////
////        // 设置Map集合属性
////        Map<String, String> countries = new HashMap<>();
////        countries.put("zg", "china");
////        countries.put("en", "english");
////        user.setCountries(countries);
//
//        return user;
//    }
//
//    /**
//     * 通过构造器创建Student实体Bean
//     * 演示构造器注入方式
//     * @return 配置好的Student实例
//     */
//    @Bean
//    public Student student() {
//        // 使用构造方法注入属性值
//        return new Student(1, "cc", "male", 20);
//    }
//
//    // ============== 3. 数据源配置 ==============
//
//    /**
//     * 创建Druid数据源Bean（连接池）
//     * 使用@PropertySource加载的属性值
//     * 指定初始化方法和销毁方法
//     * @param env Spring环境对象（用于获取属性值）
//     * @return 配置好的数据源实例
//     */
//    @Bean(initMethod = "init", destroyMethod = "close")  // 指定生命周期方法
//    public DruidDataSource dataSource(Environment env) {
//        DruidDataSource ds = new DruidDataSource();
//        // 从jdbc.properties读取配置
//        ds.setDriverClassName(env.getProperty("jdbc.driverClass"));
//        ds.setUrl(env.getProperty("jdbc.url"));
//        ds.setUsername(env.getProperty("jdbc.username"));
//        ds.setPassword(env.getProperty("jdbc.password"));
//        // 连接池参数配置（字符串转整数）
//        ds.setInitialSize(Integer.parseInt(env.getProperty("jdbc.init")));
//        ds.setMinIdle(Integer.parseInt(env.getProperty("jdbc.minIdle")));
//        ds.setMaxActive(Integer.parseInt(env.getProperty("jdbc.maxActive")));
//        // 固定参数配置
//        ds.setMaxWait(60000);  // 最大等待时间(毫秒)
//        ds.setTimeBetweenEvictionRunsMillis(60000);  // 检测间隔
//        ds.setMinEvictableIdleTimeMillis(300000);    // 最小空闲时间
//        return ds;
//    }
//
//    // ============== 4. MyBatis集成 ==============
//
//    /**
//     * 创建MyBatis的SqlSessionFactory
//     * 依赖注入上面定义的数据源
//     * @param dataSource Druid数据源Bean
//     * @return 配置好的SqlSessionFactoryBean
//     */
//    @Bean
//    public SqlSessionFactoryBean sqlSessionFactory(DruidDataSource dataSource) {
//        SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
//        factory.setDataSource(dataSource);  // 注入数据源
//
//        try {
//            // 设置Mapper XML文件位置（类路径下的dao包）
//            factory.setMapperLocations(new PathMatchingResourcePatternResolver()
//                    .getResources("classpath:dao/*.xml"));
//        } catch (IOException e) {
//            e.printStackTrace();  // 异常处理（实际生产需更严谨）
//        }
//
//        // 设置实体类别名扫描包
//        factory.setTypeAliasesPackage("entity");
//        return factory;
//    }
//
//    /**
//     * 配置Mapper接口扫描器
//     * 自动将dao包中的接口注册为Mapper
//     * @return 配置好的扫描器
//     */
//    @Bean
//    public MapperScannerConfigurer mapperScannerConfigurer() {
//        MapperScannerConfigurer configurer = new MapperScannerConfigurer();
//        configurer.setBasePackage("dao");  // 设置扫描包
//        // 引用上面定义的sqlSessionFactory
//        configurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
//        return configurer;
//    }
//
//    // ============== 5. AOP和事务配置 ==============
//
//    // 定义通知类Bean
//    @Bean
//    public MyBeforeAdvice before() {
//        return new MyBeforeAdvice();  // 前置通知
//    }
//
//    @Bean
//    public MyAfterAdvice after() {
//        return new MyAfterAdvice();    // 后置通知
//    }
//
//    @Bean
//    public MyAroundAdvice aroundAdvice() {
//        return new MyAroundAdvice();  // 环绕通知
//    }
//
//    /**
//     * 创建事务管理器Bean
//     * 依赖注入数据源
//     * @param dataSource 数据源Bean
//     * @return 平台事务管理器
//     */
//    @Bean
//    public PlatformTransactionManager transactionManager(DataSource dataSource) {
//        // 创建基于数据源的事务管理器
//        return new DataSourceTransactionManager(dataSource);
//    }
//
//    /**
//     * 创建切入点（使用正则表达式匹配方法）
//     * 匹配所有类中名为"queryUsers"的方法
//     * @return 配置好的切入点
//     */
//    @Bean
//    public JdkRegexpMethodPointcut pc_shine() {
//        JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();
//        pointcut.setPattern(".*queryUsers");  // 正则表达式
//        return pointcut;
//    }
//
//    /**
//     * 创建前置通知器（将切入点与通知组合）
//     * @return 配置好的通知器
//     */
//    @Bean
//    public DefaultPointcutAdvisor beforeAdvisor() {
//        // 组合切入点(pc_shine)和前置通知(before)
//        return new DefaultPointcutAdvisor(pc_shine(), before());
//    }
//
//    /**
//     * 创建后置通知器
//     * @return 配置好的通知器
//     */
//    @Bean
//    public DefaultPointcutAdvisor afterAdvisor() {
//        // 组合相同切入点和后置通知(after)
//        return new DefaultPointcutAdvisor(pc_shine(), after());
//    }
//
//
//    // 定义切点表达式（建议改为更通用的匹配方式）
//    @Pointcut("execution(* service.*.*(..))") // 请根据实际包名修改
//    public void serviceMethods() {}
//
//    // 定义环绕通知方法
//    @Around("serviceMethods()")
//    public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
//        // 调用自定义通知逻辑
//        MyAroundAdvice advice = aroundAdvice();
//        return advice.aroundMethod(pjp);
//    }
}
